package org.common.utils.net.netty.bytes;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.common.utils.net.netty.bytes.entity.DefaultByteMessage;
import org.common.utils.net.netty.core.NettyEncode;
import org.common.utils.net.netty.bytes.exception.NotDefaultByteMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;

/**
 * 默认的Byte编码器, 数据格式为：| 类型(1) | 序列号(8) | 消息号(8) | 数据长度(4) | 数据 |
 * @author zhouzhibing
 * @date 2025/11/13 18:51
 */
@ChannelHandler.Sharable
public class DefaultByteEncode extends NettyEncode {
    private static final Logger log = LoggerFactory.getLogger(DefaultByteEncode.class);

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) {
        if(msg instanceof DefaultByteMessage message) {
            try {
                ByteBuffer buffer = newByteBuffer(message);
                out.writeBytes(buffer.array());
            } catch (Exception e) {
                log.error("encode error , message = {}" , message , e);
            }
        } else {
            log.error("msg is not DefaultByteMessage , message = {}" , msg , new NotDefaultByteMessage());
        }
    }

    /**
     * 创建ByteBuffer
     * @param message netty消息对象
     * @return ByteBuffer
     */
    private ByteBuffer newByteBuffer(DefaultByteMessage message) {
        int dataLength = message.getData() != null ? message.getData().length : 0;
        int size = Const.HEADER_LENGTH + dataLength;

        ByteBuffer buffer = ByteBuffer.allocate(size);
//        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.put(message.getType());
        buffer.putLong(message.getSerialNo());
        buffer.putLong(message.getMessageId());
        buffer.putInt(dataLength);

        if(dataLength > 0) {
            buffer.put(message.getData());
        }

//        log.info("encode message success , serialNo = {} , array = {}" , message.getSerialNo() , Arrays.toString(buffer.array()));
        return buffer;
    }
}
